home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / encore.lha / encore / tsystem / dynload.c next >
C/C++ Source or Header  |  1988-06-10  |  11KB  |  405 lines

  1. /*
  2.  *            D Y N L O A D . C 
  3.  *
  4.  * This file contains functions to help dynamically load foreign UNIX files
  5.  * into a running T process.
  6.  *
  7.  * written by Dorab Patel <dorab@neptune.cs.ucla.edu>
  8.  * December 24, 1986
  9.  * Copyright Dorab Patel (C) 1986
  10.  * Permission is given to distribute this software free to anyone
  11.  * using it for a non-commercial purpose. Comments/bug reports/fixes
  12.  * are encouraged.
  13.  *
  14.  * $Revision: 1.1 $
  15.  *
  16.  * $Log:    dynload.c,v $
  17.  * Revision 1.1  86/12/24  18:20:44  dorab
  18.  * Initial Revision
  19.  * 
  20.  */
  21. #ifndef lint
  22. static char RCSid[] = "@(#)$Header: dynload.c,v 1.1 86/12/24 18:20:44 dorab UCLA $ (Exp)";
  23. #endif
  24.  
  25. #include <stdio.h>        /* for obvious reasons */
  26. #include <a.out.h>        /* for obvious reasons */
  27. #include <sys/types.h>        /* for caddr_t */
  28. #include <strings.h>        /* for strlen */
  29.  
  30. /*
  31.  * dont turn this on unless you want copious debugging.
  32.  * it may also have unwanted interactions with sbrk.
  33.  */
  34. #undef DEBUG
  35.  
  36. /*
  37.  * alloca is used by default for efficiency. if you need to use
  38.  * malloc, then define USE_MALLOC
  39.  */
  40. #undef USE_MALLOC
  41.  
  42. /* forward declarations */
  43. caddr_t sbrk();
  44. char *sprintf();
  45. #ifdef USE_MALLOC
  46. char *malloc();
  47. #else ~USE_MALLOC
  48. char *alloca();
  49. #endif ~USE_MALLOC
  50.  
  51. /*
  52.  * loadhelp takes an object file (objFile), and loads it
  53.  * into the current process, using relocation information found in the
  54.  * namelist of relocFile. In the process, it will create
  55.  * tmpFile, which has all the current relocation info and which can
  56.  * be used for a subsequent load. In addition, libString
  57.  * is used to search any required libraries.
  58.  * otherString can be used for other ld arguments.
  59.  * Returns 0 if all ok, >0 otherwise.
  60.  * It closes all files it has opened and unlinks the temp file
  61.  * if there has been an error.
  62.  * 
  63.  * TODO:
  64.  * do i need to round up the text/data sizes to word boundaries ?
  65.  */
  66.  
  67. /*
  68.  * the sprintf string for the ld command
  69.  * if this changes, also modify the code for ldCmdSpace
  70.  */
  71. #define LoadCommandTemplate "/bin/ld -N -x -A %s -T %lx %s %s -o %s %s -lc"
  72.  
  73. int
  74. loadhelp(objFile, relocFile, tmpFile, libString, otherString)
  75. char *objFile, *relocFile, *tmpFile, *libString, *otherString;
  76. {
  77. char *loadCommand;        /* pointer to string containing the ld cmd */
  78. int ldCmdSpace;            /* space allocated for ld command */
  79. char buf[BUFSIZ];        /* for buffering tmpFile i/o */
  80. struct exec hdr;
  81. long loadPoint, endOfMem, pageSize, tmp;
  82. FILE *tmpFD = NULL;
  83. long bytesToRead, bytesToExtend;
  84.  
  85. /*
  86.  * calculate the length of the ld command and allocate memory for it
  87.  * this code would need changing if LoadCommandTemplate was changed
  88.  */
  89. ldCmdSpace = strlen(LoadCommandTemplate);
  90. ldCmdSpace += strlen(objFile) + strlen(relocFile) + strlen(tmpFile);
  91. ldCmdSpace += strlen(libString) + strlen(otherString);
  92. ldCmdSpace += 16;    /* 10 for loadPoint + 1 for null + fudge of 5 */
  93.  
  94. #ifdef DEBUG
  95. (void)fprintf(stderr,"loadhelp: ld cmd needs %d bytes\n", ldCmdSpace);
  96. #endif DEBUG
  97.  
  98. #ifdef USE_MALLOC
  99. loadCommand = malloc((unsigned)ldCmdSpace);
  100. #else ~USE_MALLOC
  101. loadCommand = alloca(ldCmdSpace);
  102. #endif ~USE_MALLOC
  103.  
  104. if ((long)loadCommand == 0) {
  105. #ifdef DEBUG
  106.     perror("loadhelp");
  107.     (void)fprintf(stderr,
  108.               "loadhelp: could not allocate %d bytes for ld cmd\n",
  109.               ldCmdSpace);
  110. #endif DEBUG
  111. #ifdef USE_MALLOC
  112.     free(loadCommand);
  113. #endif USE_MALLOC
  114.     return(1);
  115.     }
  116.  
  117. pageSize = (long) getpagesize(); /* works on vaxen and suns */
  118. /* there is a strong assumption that pageSize is a power of 2 */
  119.  
  120. #ifdef DEBUG
  121. (void)fprintf(stderr,"loadhelp: page size is %ld (%lx)\n", pageSize, pageSize);
  122. #endif DEBUG
  123.  
  124. endOfMem = (long) sbrk(0); /* get end of current memory */
  125. if (endOfMem < 0) {
  126. #ifdef DEBUG
  127.     perror("loadhelp");
  128.     (void)fprintf(stderr,"loadhelp: sbrk(0) failed\n");
  129. #endif DEBUG
  130. #ifdef USE_MALLOC
  131.     free(loadCommand);
  132. #endif USE_MALLOC
  133.     return(2);
  134.     }
  135.  
  136. #ifdef DEBUG
  137. (void)fprintf(stderr,"loadhelp: end of memory = %ld (%lx)\n",
  138.                 endOfMem, endOfMem);
  139. #endif DEBUG
  140.  
  141. /* round up to the next higher pageSize */
  142. loadPoint = (long) sbrk((int)(pageSize - (endOfMem & (pageSize - 1L))));
  143.  
  144. if (loadPoint < 0L) {
  145. #ifdef DEBUG
  146.     perror("loadhelp");
  147.     (void)fprintf(stderr,"loadhelp: could not bump upto pagesize\n");
  148. #endif DEBUG
  149. #ifdef USE_MALLOC
  150.     free(loadCommand);
  151. #endif USE_MALLOC
  152.     return(3);
  153.     }
  154.  
  155. loadPoint = (long) sbrk(0);
  156. /*
  157.  * there had better be no further calls to sbrk explicitly or implicitly
  158.  * (e.g. via calling printf or something like that) until the loading is
  159.  * over.
  160.  */
  161.  
  162. /* sanity check */
  163. if (loadPoint < 0L || ((loadPoint & (pageSize - 1L)) != 0L)) {
  164. #ifdef DEBUG
  165.     perror("loadhelp");
  166.     (void)fprintf(stderr,"loadhelp: not page aligned\n");
  167. #endif DEBUG
  168. #ifdef USE_MALLOC
  169.     free(loadCommand);
  170. #endif USE_MALLOC
  171.     return(4);
  172.     }
  173.  
  174. #ifdef DEBUG
  175. (void)fprintf(stderr,"loadhelp: load point is %ld (%lx)\n",
  176.                 loadPoint, loadPoint);
  177. #endif DEBUG
  178.  
  179. (void)sprintf(loadCommand, LoadCommandTemplate,
  180.     relocFile, loadPoint, otherString, objFile, tmpFile, libString);
  181.  
  182. /* if the sprintf overflows it'll probably botch BAD, but just in case */
  183. if (strlen(loadCommand) >= ldCmdSpace) {
  184. #ifdef DEBUG
  185.     (void)fprintf(stderr,
  186.               "loadhelp: load command greater than %d byte buffer\n",
  187.               ldCmdSpace);
  188. #endif DEBUG
  189. #ifdef USE_MALLOC
  190.     free(loadCommand);
  191. #endif USE_MALLOC
  192.     return(5);
  193.     }
  194.  
  195. #ifdef DEBUG
  196. (void)fprintf(stderr,"loadhelp: the load command is \"%s\"\n", loadCommand);
  197. #endif DEBUG
  198.  
  199. /* run the ld comand to do relocation */
  200. if (system(loadCommand) != 0 ) {
  201. #ifdef DEBUG
  202.     perror("loadhelp");
  203.     (void)fprintf(stderr,"loadhelp: error in executing the ld command\n");
  204. #endif DEBUG
  205. #ifdef USE_MALLOC
  206.     free(loadCommand);
  207. #endif USE_MALLOC
  208.     return(6);
  209.     }
  210.  
  211. /* open the relocated file */
  212. tmpFD = fopen(tmpFile, "r");
  213. if (tmpFD == NULL ) {
  214. #ifdef DEBUG
  215.     perror("loadhelp");
  216.     (void)fprintf(stderr, "loadhelp: could not open %s for read\n",
  217.                   tmpFile);
  218. #endif DEBUG
  219. #ifdef USE_MALLOC
  220.     free(loadCommand);
  221. #endif USE_MALLOC
  222.     return(7);
  223.     }
  224.  
  225. /*
  226.  * use buf to buffer tmpFile so that no mallocs can occur
  227.  * since buf is automatic, tmpFD must be closed upon exit from this routine
  228.  */
  229. (void)setbuf(tmpFD,buf);
  230.  
  231. /* read its header */
  232. if (fread((char *)&hdr, sizeof(struct exec), 1, tmpFD) != 1) {
  233. #ifdef DEBUG
  234.     perror("loadhelp");
  235.     (void)fprintf(stderr,"loadhelp: error reading header of %s\n", tmpFile);
  236.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  237.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  238. #else ~DEBUG
  239.     (void)fclose(tmpFD);    /* close tmp file */
  240.     (void)unlink(tmpFile);    /* remove it */
  241. #endif ~DEBUG
  242. #ifdef USE_MALLOC
  243.     free(loadCommand);
  244. #endif USE_MALLOC
  245.     return(8);
  246.     }
  247.  
  248. if (N_BADMAG(hdr)) {
  249. #ifdef DEBUG
  250.     (void)fprintf(stderr,"loadhelp: bad magic number %o in %s\n",
  251.                   hdr.a_magic, tmpFile);
  252.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  253.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  254. #else ~DEBUG
  255.     (void)fclose(tmpFD);    /* close tmp file */
  256.     (void)unlink(tmpFile);    /* remove it */
  257. #endif ~DEBUG
  258. #ifdef USE_MALLOC
  259.     free(loadCommand);
  260. #endif USE_MALLOC
  261.     return(9);
  262.     }
  263.  
  264. #ifdef DEBUG
  265. (void)fprintf(stderr,
  266.   "loadhelp: magic = %o, text = %ld(%lx), data = %ld(%lx), bss = %ld(%lx)\n",
  267.                hdr.a_magic, hdr.a_text,
  268.                hdr.a_text, hdr.a_data,
  269.                hdr.a_data, hdr.a_bss, hdr.a_bss);
  270. #endif DEBUG
  271.  
  272. bytesToRead = hdr.a_text + hdr.a_data;
  273. bytesToExtend = bytesToRead + hdr.a_bss;
  274.  
  275. #ifdef DEBUG
  276. (void)fprintf(stderr,
  277.           "loadhelp: going to read %ld bytes and extend by %ld bytes\n",
  278.                bytesToRead, bytesToExtend);
  279. #endif DEBUG
  280.  
  281. /* get required memory */
  282. tmp = (long) sbrk((int)bytesToExtend);
  283. if (tmp < 0L) {
  284. #ifdef DEBUG
  285.     perror("loadhelp");
  286.     (void)fprintf(stderr,"loadhelp: not enough memory\n");
  287.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  288.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  289. #else ~DEBUG
  290.     (void)fclose(tmpFD);    /* close tmp file */
  291.     (void)unlink(tmpFile);    /* remove it */
  292. #endif ~DEBUG
  293. #ifdef USE_MALLOC
  294.     free(loadCommand);
  295. #endif USE_MALLOC
  296.     return(10);
  297.     }
  298.  
  299. /* some last sanity checks */
  300. if (tmp != loadPoint) {
  301. #ifdef DEBUG
  302.     (void)fprintf(stderr,
  303.               "loadhelp: load point is %ld but sbrk returns %ld\n",
  304.                   loadPoint, tmp);
  305.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  306.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  307. #else ~DEBUG
  308.     (void)fclose(tmpFD);    /* close tmp file */
  309.     (void)unlink(tmpFile);    /* remove it */
  310. #endif ~DEBUG
  311. #ifdef USE_MALLOC
  312.     free(loadCommand);
  313. #endif USE_MALLOC
  314.     return(11);
  315.     }
  316.  
  317. if (tmp & (pageSize - 1L)) {
  318. #ifdef DEBUG
  319.     (void)fprintf(stderr,
  320.               "loadhelp: allocated memory at %ld -not page aligned\n");
  321.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  322.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  323. #else ~DEBUG
  324.     (void)fclose(tmpFD);    /* close tmp file */
  325.     (void)unlink(tmpFile);    /* remove it */
  326. #endif ~DEBUG
  327. #ifdef USE_MALLOC
  328.     free(loadCommand);
  329. #endif USE_MALLOC
  330.     return(12);
  331.     }
  332.  
  333. /* go to beginning of text */
  334. if (fseek(tmpFD,(long)N_TXTOFF(hdr),0) < 0) {
  335. #ifdef DEBUG
  336.     perror("loadhelp");
  337.     (void)fprintf(stderr,"loadhelp: fseek failed on %s\n", tmpFile);
  338.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  339.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  340. #else ~DEBUG
  341.     (void)fclose(tmpFD);    /* close tmp file */
  342.     (void)unlink(tmpFile);    /* remove it */
  343. #endif ~DEBUG
  344. #ifdef USE_MALLOC
  345.     free(loadCommand);
  346. #endif USE_MALLOC
  347.     return(13);
  348.     }
  349.  
  350. /* read the text and data segments in */
  351. if (fread((char *)loadPoint, 1, (int)bytesToRead, tmpFD) != (int)bytesToRead) {
  352. #ifdef DEBUG
  353.     perror("loadhelp");
  354.     (void)fprintf(stderr, "loadhelp: could not read data from %s\n",
  355.                   tmpFile);
  356.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  357.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  358. #else ~DEBUG
  359.     (void)fclose(tmpFD);    /* close tmp file */
  360.     (void)unlink(tmpFile);    /* remove it */
  361. #endif ~DEBUG
  362. #ifdef USE_MALLOC
  363.     free(loadCommand);
  364. #endif USE_MALLOC
  365.     return(14);
  366.     }
  367.  
  368. #ifdef DEBUG
  369. if (fclose(tmpFD) == EOF) perror("loadhelp");
  370. #else ~DEBUG
  371. (void)fclose(tmpFD);
  372. #endif ~DEBUG
  373.  
  374. #ifdef USE_MALLOC
  375. free(loadCommand);
  376. #endif USE_MALLOC
  377.  
  378. return(0);
  379. }
  380.  
  381.  
  382. /*
  383.  * return the address of the function functionName in the namelist 
  384.  * of the file fileName.
  385.  * the calling procedure had better make sure that fileName exists.
  386.  */
  387. unsigned long
  388. nlistone(fileName,functionName)
  389. char *fileName, *functionName;
  390. {
  391. struct nlist nl[2];
  392. int rc;
  393.  
  394. nl[1].n_un.n_name = '\0'; /* terminate the name list */
  395. nl[0].n_un.n_name = functionName; /* put the function name in */
  396. rc = nlist(fileName,nl); /* call nlist */
  397. if (rc < 0 || (nl[0].n_type == (unsigned char) 0 /* check for errors */
  398.        && nl[0].n_value == (unsigned long) 0))
  399.     return ((unsigned long) 0);
  400. if (nl[0].n_type & N_TEXT) /* if it is in the text segment i.e. is a function */
  401.     return(nl[0].n_value); /* return the address */
  402. else
  403.     return ((unsigned long) 0); /* not a function */
  404. }
  405.